{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "github地址:[https://github.com/cheesezh/python_design_patterns](https://github.com/cheesezh/python_design_patterns)\n",
    "    \n",
    "## 题目1\n",
    "用程序模拟，顾客直接向烤串师傅提需求。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "烤羊肉串\n",
      "烤羊肉串\n",
      "烤羊肉串\n",
      "烤鸡翅\n",
      "烤羊肉串\n",
      "烤羊肉串\n",
      "烤鸡翅\n"
     ]
    }
   ],
   "source": [
    "class Barbecuer():\n",
    "    \n",
    "    def bake_mutton(self):\n",
    "        print(\"烤羊肉串\")\n",
    "        \n",
    "    def bake_chicken_wing(self):\n",
    "        print(\"烤鸡翅\")\n",
    "        \n",
    "        \n",
    "def main():\n",
    "    boy = Barbecuer()\n",
    "    boy.bake_mutton()\n",
    "    boy.bake_mutton()\n",
    "    boy.bake_mutton()\n",
    "    boy.bake_chicken_wing()\n",
    "    boy.bake_mutton()\n",
    "    boy.bake_mutton()\n",
    "    boy.bake_chicken_wing()\n",
    "    \n",
    "main()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 点评\n",
    "客户端程序与“烤串师傅”紧耦合，尽管简单，但是极为僵化，当顾客多了，请求多了，就容易乱了。\n",
    "\n",
    "## 题目2\n",
    "用程序模拟，顾客向服务员提需求，服务员再告知烤串师傅。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "增加订单: 烤羊肉串\n",
      "增加订单: 烤羊肉串\n",
      "鸡翅没了，换点其他的吧\n",
      "烤羊肉串\n",
      "烤羊肉串\n"
     ]
    }
   ],
   "source": [
    "from abc import ABCMeta, abstractmethod\n",
    "\n",
    "\n",
    "class Command():\n",
    "    \"\"\"\n",
    "    抽象命令类\n",
    "    \"\"\"\n",
    "    __metaclass__ = ABCMeta\n",
    "    \n",
    "    # 需要确定一个命令接收者\n",
    "    def __init__(self, receiver):\n",
    "        self.receiver = receiver\n",
    "        \n",
    "    @abstractmethod\n",
    "    def excute_command(self):\n",
    "        pass\n",
    "    \n",
    "    \n",
    "class BakeMuttonCommand(Command):\n",
    "    \"\"\"\n",
    "    具体命令类\n",
    "    \"\"\"\n",
    "    def excute_command(self):\n",
    "        self.receiver.bake_mutton()\n",
    "        \n",
    "    def to_string(self):\n",
    "        return \"烤羊肉串\"\n",
    "        \n",
    "\n",
    "class BakeChickenWingCommand(Command):\n",
    "    \"\"\"\n",
    "    具体命令类\n",
    "    \"\"\"\n",
    "    def excute_command(self):\n",
    "        self.receiver.bake_chicken_wing()\n",
    "        \n",
    "    def to_string(self):\n",
    "        return \"烤鸡翅\"\n",
    "        \n",
    "        \n",
    "class Waiter():\n",
    "    \"\"\"\n",
    "    服务员类, 不用管顾客的烤串要怎么烤，对于服务员来说，都当作命令记录下来就行，然后通知“烤串师傅”执行即可。\n",
    "    \"\"\"\n",
    "    def __init__(self):\n",
    "        self.orders = []\n",
    "        \n",
    "    def set_order(self, cmd):\n",
    "        if cmd.to_string() == \"烤鸡翅\":\n",
    "            print(\"鸡翅没了，换点其他的吧\")\n",
    "        else:\n",
    "            self.orders.append(cmd)\n",
    "            print(\"增加订单:\", cmd.to_string())\n",
    "    \n",
    "    def cancel_order(self, cmd):\n",
    "        self.orders.remove(cmd)\n",
    "        print(\"取消订单:\", cmd.to_string())\n",
    "        \n",
    "    def notify(self):\n",
    "        for cmd in self.orders:\n",
    "            cmd.excute_command()\n",
    "            \n",
    "\n",
    "def main():\n",
    "    # 开店准备\n",
    "    boy = Barbecuer()\n",
    "    bake_mutton_1 = BakeMuttonCommand(boy)\n",
    "    bake_mutton_2 = BakeMuttonCommand(boy)\n",
    "    bake_chicken_wing = BakeChickenWingCommand(boy)\n",
    "    girl = Waiter()\n",
    "    \n",
    "    # 开门营业\n",
    "    girl.set_order(bake_mutton_1)\n",
    "    girl.set_order(bake_mutton_2)\n",
    "    girl.set_order(bake_chicken_wing)\n",
    "    \n",
    "    # 开始制作\n",
    "    girl.notify()\n",
    "            \n",
    "main()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 命令模式\n",
    "\n",
    "命令模式，讲一个请求封装成一个对象，从而使你可用不同的请求对客户进行参数化；对请求排队或记录请求日志，以及支持可撤销操作。[DP]\n",
    "\n",
    "主要包括以下几种类：\n",
    "\n",
    "- Command类，用来声明执行操作的接口，每个Command类都需要绑定一个命令接收者(执行者)；\n",
    "- ConcreteCommand类，将一个命令接收者对象绑定与一个动作，调用接收者相应的操作，以实现Execute；\n",
    "- Invoder类，比如服务员，维护命令队列，发起执行命令的请求；\n",
    "- Receiver类，知道如何实施执行一个与请求相关的操作，任何类都可能作为一个接收者；\n",
    "\n",
    "命令模式的优点：\n",
    "\n",
    "- 它能较容易的设计一个命令队列；\n",
    "- 在需要的情况下，可以较容易的将命令记入日志；\n",
    "- 允许接收请求的一方决定是否要否决请求；\n",
    "- 可以容易的实现对请求的撤销和崇左；\n",
    "- 加进新的具体命令类不影响其他的类；\n",
    "- 把[请求一个操作的对象]和[知道怎么执行一个操作的对象]隔离;"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.4"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
